#include "bsp_CO_Com.h"
#include "bsp_RingBuffer.h"
#include "bsp_port.h"

#define bsp_USARTx USART1                    // 选择串口
#define bsp_DMAx DMA1                        // STM32CuMx中配置的DMA(串口发送以DMA的方式发送)
#define bsp_LL_DMA_CHANNELx LL_DMA_CHANNEL_2 // STM32CuMx中DMA的通道

#define RB_FIFO_MAX_SIZE (64)
RingBuffer_Typedef UART_BUF;

uint16_t crc;
unsigned char buff[RB_FIFO_MAX_SIZE]; // 数据缓存区域

/*  @brief  CRC8校验
    @param  *p_buffer
            数据
    @param  buf_size
            数据长度
    @return 无
    @property 无
*/
static uint8_t crc8(uint8_t *p_buffer, uint16_t buf_size)
{
    uint8_t crc = 0;
    uint8_t i = 0;

    if (buf_size <= 0)
    {
        return crc;
    }

    while (buf_size--)
    {
        for (i = 0x80; i != 0; i /= 2)
        {
            if ((crc & 0x80) != 0)
            {
                crc *= 2;
                crc ^= 0x07;
            }
            else
            {
                crc *= 2;
            }

            if ((*p_buffer & i) != 0)
            {
                crc ^= 0x07;
            }
        }

        p_buffer++;
    }

    return crc;
}

uint8_t CRC8(uint8_t *p_buffer, uint16_t buf_size)
{
    return crc8(p_buffer, buf_size);
}

/*  @brief  命令字处理 函数
    @param  Byte[]
            需要处理的数组
    @param  length
            数组的长度
    @return 无
    @property 无
*/
void Data_CMD_Handler(unsigned char Byte[], unsigned char length)
{
    uint8_t cmd = Byte[3]; // 后去命令字

    switch (cmd)
    {
    case 0x01: // 金属探测
    {
    }
    break;

    default:
        break;
    }
}

/*	@brief  数据处理函数
    @param  Byte[]
            需要处理的数组
    @param  length
            数组的长度
    @return 无
    @property
*/
void Data_Verify(unsigned char Byte[], unsigned char length)
{
    uint8_t crc;
    // 帧头、地址、长度校验
    if (Byte[0] != 0xF7 || Byte[1] != 0xAA || length < Byte[2])
    {
        return;
    }

    /*CRC8校验*/
    crc = CRC8(Byte, length - 1);
    if (crc != Byte[length - 1])
    {
        Byte[length - 1] = crc;
        bsp_USART1_SendBytes(Byte, length); // 回复错误
        return;
    }

    Data_CMD_Handler(Byte, length); // 命令字处理
}

/*  @brief  bsp_USARTx 数据处理函数
    @return 无
    @property 放在主函数中
*/
void bsp_USART_485_Handler(void)
{
    uint8_t datalen = 0;
    uint8_t Datasize = 0;
    do
    {
        datalen = RB_ReadBytes(&UART_BUF, buff + Datasize, RB_FIFO_MAX_SIZE);
        Datasize += datalen;
        LL_mDelay(5);
    } while (datalen);

    if (Datasize > 4) // 如果接收到的数据长度小于4个字节，就不发送
    {
        // bsp_USART_485_DMA_SendBytes(buff, Datasize); // 调试时用
        Data_Verify(buff, Datasize); // 去应用层处理
    }
}

// 串口调试函数
void bsp_USART_485_Debug(void)
{
    //    uint8_t abcBuff[5] = {0x55, 0x55, 0x55, 0x55, 0x55};

    while (1)
    {
        bsp_USART_485_Handler();
        LL_mDelay(1000);
    }
}
